#include <rpcFw\VarCodec.h>



Variant DVarCodec::parseItem(cJSON* pJsonStruct, char *keyName, bool bArray)
{
	Variant varObject;

	while (pJsonStruct){
		Variant varData;
		switch (pJsonStruct->type)
		{
		case cJSON_False:
		{
			varData.bData = false;
			varData.dataType = Variant::VAR_BOOL;
		}
		break;
		case cJSON_True:
		{
			varData.bData = true;
			varData.dataType = Variant::VAR_BOOL;
		}
		break;
		case cJSON_NULL:
		{
			varData.dataType = Variant::VAR_NULL;
		}
		break;
		case cJSON_Number:
		{
			varData.dData = pJsonStruct->valuedouble;
			varData.dataType = Variant::VAR_DOUBLE;
		}
		break;
		case cJSON_String:
		{
			varData.strData = pJsonStruct->valuestring;
			varData.dataType = Variant::VAR_STRING;
		}
		break;
		case cJSON_Array:
		{
			varData = parseItem(pJsonStruct->child, nullptr, true);
			varData.dataType = Variant::VAR_VECTOR;
		}
		break;
		case cJSON_Object:
		{
			varData = parseItem(pJsonStruct->child, pJsonStruct->string);
			varData.dataType = Variant::VAR_MAP;
		}
		break;
		}

		if (pJsonStruct->string != nullptr)
		{
			varObject.mapData[std::string(pJsonStruct->string)] = varData;
		}
		else
		{
			if (bArray)
			{
				varObject.vecData.push_back(varData);
			}
			else
			{
				varObject = varData;
			}
		}

		pJsonStruct = pJsonStruct->next;
	}

	return varObject;
}

Variant DVarCodec::unpack(const char *jsonStr){
	cJSON* pJsonStruct = cJSON_Parse(jsonStr);
	if (pJsonStruct == NULL)
	{
		std::cout << std::string("prase json string error at ") + cJSON_GetErrorPtr();
		return(false);
	}

	Variant varData = parseItem(pJsonStruct, "");


	return varData;
}

std::string DVarCodec::pack(Variant &varObject, bool bFormat)
{
	cJSON *json = packItem(varObject);

	std::string jsonStr = bFormat ? cJSON_Print(json) : cJSON_PrintUnformatted(json);

	return jsonStr;
}

cJSON * DVarCodec::packItem(Variant &varObject){
	cJSON *cJsonObj;
	cJSON *tpObj;


	switch (varObject.dataType)
	{
	case Variant::VAR_BOOL:
	{
		cJsonObj = cJSON_CreateBool(varObject.bData);
	}
	break;
	case Variant::VAR_NULL:
	{
		cJsonObj = cJSON_CreateNull();
	}
	break;
	case Variant::VAR_INT:
	{
		cJsonObj = cJSON_CreateNumber (varObject.iData);
	}
	break;
	case Variant::VAR_DOUBLE:
	{
		cJsonObj = cJSON_CreateNumber(varObject.dData);
	}
	break;
	case Variant::VAR_STRING:
	{
		cJsonObj = cJSON_CreateString(varObject.strData.c_str());
	}
	break;
	case Variant::VAR_VECTOR:
	{
		cJsonObj = cJSON_CreateArray();
		for (size_t i = 0; i < varObject.vecData.size(); i++)
		{
			tpObj = packItem(varObject.vecData[i]);
			cJSON_AddItemToArray(cJsonObj, tpObj);
		}
	}
	break;
	case Variant::VAR_MAP:
	{
		cJsonObj = cJSON_CreateObject();
		for (auto &iter : varObject.mapData)
		{
			tpObj = packItem(iter.second);
			cJSON_AddItemToObject(cJsonObj, iter.first.c_str(), tpObj);
		}
	}
	break;
	}

	return cJsonObj;
}
